﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using SapaFinance.Domain.Model;
using SapaFinance.Domain.Specifications.Obsolete;
using SapaFinance.GenericRepository;

namespace SapaFinance.Infrastructure.Repository
{
    public class MemoryRepository<T> : IGenericRepository<T, Guid> where T : AbstractEntity
    {
        private readonly HashSet<T> memorySet;

        public MemoryRepository()
        {
            memorySet = new HashSet<T>();
        }

        #region IGenericRepositoryReadOnly<T,Guid> Members

        public T GetById(Guid id)
        {
            return FindBy(x => x.UID == id);
        }

        public IList<T> GetAll()
        {
            return GetAllAsQueryable().ToList();
        }

        public TSpecification Specify<TSpecification>() where TSpecification : class, GenericRepository.ISpecification<T>
        {
            throw new NotImplementedException();
        }

        #endregion

        public bool Add(T entity)
        {
            memorySet.Add(entity);
            return true;
        }

        public bool Add(IEnumerable<T> items)
        {
            foreach (var item in items)
                memorySet.Add(item);
            return true;
        }

        public void Insert(T entity)
        {
            Add(entity);
        }

        public void Update(T entity)
        {
            memorySet.Add(entity);
            
        }

        public void Delete(T entity)
        {
            memorySet.Remove(entity);
        }

        public bool Delete(IEnumerable<T> entities)
        {
            foreach (var entity in entities)
                memorySet.Remove(entity);
            return true;
        }

        public T FindBy(Expression<Func<T, bool>> expression)
        {
            return FilterBy(expression).Single();
            //return All().SingleOrDefault(expression);
        }

        public IQueryable<T> FilterBy(Expression<Func<T, bool>> expression)
        {
            return GetAllAsQueryable().Where(expression).AsQueryable();
        }

        public T FindBy(Specification<T> criteria)
        {
            return FilterBy(criteria).Single();
        }

        public IQueryable<T> FilterBy(Specification<T> criteria)
        {
            return GetAllAsQueryable().Where(criteria.IsSatisfiedBy()).AsQueryable();
        }

        public IQueryable<T> GetAllAsQueryable()
        {
            return memorySet.AsQueryable();
        }
    }
}